﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace ReflectionDemo
{
    /// <summary>
    /// 反射： 动态获取/使用程序集、模块、类中的信息
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            var aaa = typeof(string);

            object a = new AClass();
            object b = new BClass();
            object c = new CClass();
            object lista = new List<AClass>();
            object listb = new List<BClass>();

            TestObject(a);
            TestObject(b);
            TestObject(c);
            TestObject(lista);
            TestObject(listb);

            //GetAllList();
            CallFunction();
        }

        static void TestObject(object obj)
        {
            if(obj is AClass aa)
            {
                
            }

            switch (obj)
            {
                case BClass bbb:
                    bbb.ToString();
                    break;
                case AClass aaa:
                    aaa.ToString();
                    break;
                default:
                    break;
            }

            bool test1 = obj is AClass;
            bool test2 = obj is BClass;
            bool test3 = obj is CClass;
            bool test4 = obj is IA;

            bool test5 = obj is List<AClass>;
            bool test6 = obj is IEnumerable<AClass>;

            bool test7 = obj.GetType().IsSubclassOf(typeof(AClass));

            int a = 0;
        }

        static void GetAllList()
        {
            List<Type> allTypes = typeof(string).Assembly.GetExportedTypes().ToList();

            var listTypes = allTypes.Where(x => typeof(IEnumerable).IsAssignableFrom(x) && x.IsClass).ToList();

            foreach (var item in listTypes)
            {
                Console.WriteLine(item.Name);
                var att = item.GetCustomAttributes().ToList();
                att.ForEach(x => {
                    Console.WriteLine("[" + x.ToString() + "]");
                });

                var ps = item.GetProperties().ToList();
                ps.ForEach(x => {
                    Console.WriteLine("----"+x.Name);
                });

                var ms = item.GetMethods().ToList();
                ms.ForEach(x => {
                    Console.WriteLine("----" + x.Name+"()");
                });
            }
        }

        static void CallFunction()
        {
            var dir = Directory.GetCurrentDirectory();
            var files = Directory.GetFiles(dir);
            var alltypes = new List<Type>();
            foreach (var item in files)
            {
                if(Path.GetExtension(item) == ".dll")
                {
                    var dll = Assembly.LoadFrom(item);
                    alltypes.AddRange(dll.GetTypes().Where(x => typeof(IA).IsAssignableFrom(x) && x.IsClass));
                }
            }
            foreach (var item in alltypes)
            {
                
                ConstructorInfo constructor = null;
                if (item.IsGenericType)
                {
                    constructor = item.MakeGenericType(typeof(int)).GetConstructor(Type.EmptyTypes);
                    //GenericAClass<int> test = new GenericAClass<int>();
                }
                else
                {
                    constructor = item.GetConstructor(Type.EmptyTypes);
                }
                var  ins = constructor.Invoke(null) as IA;
                ins.Test();

                //ins = Activator.CreateInstance(item);
                //var testmethod = item.GetMethod("Test");
                //testmethod?.Invoke(ins, null);
                // https://github.com/dotnetcore/Natasha
            }
        }
    }
}
